1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package sun.reflect.annotation;
27
28 import java.lang.annotation.*;
29 import java.util.*;
30 import java.nio.ByteBuffer;
31 import java.nio.BufferUnderflowException;
32 import java.lang.reflect.*;
33 import sun.reflect.ConstantPool;
34
35 import sun.reflect.generics.parser.SignatureParser;
36 import sun.reflect.generics.tree.TypeSignature;
37 import sun.reflect.generics.factory.GenericsFactory;
38 import sun.reflect.generics.factory.CoreReflectionFactory;
39 import sun.reflect.generics.visitor.Reifier;
40 import sun.reflect.generics.scope.ClassScope;
41
42
43
44
45
46
47
48
49 public class AnnotationParser {
50
51
52
53
54
55
56
57
58
59
60
61
62 public static Map<Class<? extends Annotation>, Annotation> parseAnnotations(
63 byte[] rawAnnotations,
64 ConstantPool constPool,
65 Class<?> container) {
66 if (rawAnnotations == null)
67 return Collections.emptyMap();
68
69 try {
70 return parseAnnotations2(rawAnnotations, constPool, container);
71 } catch(BufferUnderflowException e) {
72 throw new AnnotationFormatError("Unexpected end of annotations.");
73 } catch(IllegalArgumentException e) {
74
75 throw new AnnotationFormatError(e);
76 }
77 }
78
79 private static Map<Class<? extends Annotation>, Annotation> parseAnnotations2(
80 byte[] rawAnnotations,
81 ConstantPool constPool,
82 Class<?> container) {
83 Map<Class<? extends Annotation>, Annotation> result =
84 new LinkedHashMap<Class<? extends Annotation>, Annotation>();
85 ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
86 int numAnnotations = buf.getShort() & 0xFFFF;
87 for (int i = 0; i < numAnnotations; i++) {
88 Annotation a = parseAnnotation(buf, constPool, container, false);
89 if (a != null) {
90 Class<? extends Annotation> klass = a.annotationType();
91 AnnotationType type = AnnotationType.getInstance(klass);
92 if (type.retention() == RetentionPolicy.RUNTIME)
93 if (result.put(klass, a) != null)
94 throw new AnnotationFormatError(
95 "Duplicate annotation for class: "+klass+": " + a);
96 }
97 }
98 return result;
99 }
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124 public static Annotation[][] parseParameterAnnotations(
125 byte[] rawAnnotations,
126 ConstantPool constPool,
127 Class<?> container) {
128 try {
129 return parseParameterAnnotations2(rawAnnotations, constPool, container);
130 } catch(BufferUnderflowException e) {
131 throw new AnnotationFormatError(
132 "Unexpected end of parameter annotations.");
133 } catch(IllegalArgumentException e) {
134
135 throw new AnnotationFormatError(e);
136 }
137 }
138
139 private static Annotation[][] parseParameterAnnotations2(
140 byte[] rawAnnotations,
141 ConstantPool constPool,
142 Class<?> container) {
143 ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
144 int numParameters = buf.get() & 0xFF;
145 Annotation[][] result = new Annotation[numParameters][];
146
147 for (int i = 0; i < numParameters; i++) {
148 int numAnnotations = buf.getShort() & 0xFFFF;
149 List<Annotation> annotations =
150 new ArrayList<Annotation>(numAnnotations);
151 for (int j = 0; j < numAnnotations; j++) {
152 Annotation a = parseAnnotation(buf, constPool, container, false);
153 if (a != null) {
154 AnnotationType type = AnnotationType.getInstance(
155 a.annotationType());
156 if (type.retention() == RetentionPolicy.RUNTIME)
157 annotations.add(a);
158 }
159 }
160 result[i] = annotations.toArray(EMPTY_ANNOTATIONS_ARRAY);
161 }
162 return result;
163 }
164
165 private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY =
166 new Annotation[0];
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190 private static Annotation parseAnnotation(ByteBuffer buf,
191 ConstantPool constPool,
192 Class<?> container,
193 boolean exceptionOnMissingAnnotationClass) {
194 int typeIndex = buf.getShort() & 0xFFFF;
195 Class<? extends Annotation> annotationClass = null;
196 String sig = "[unknown]";
197 try {
198 try {
199 sig = constPool.getUTF8At(typeIndex);
200 annotationClass = (Class<? extends Annotation>)parseSig(sig, container);
201 } catch (IllegalArgumentException ex) {
202
203 annotationClass = constPool.getClassAt(typeIndex);
204 }
205 } catch (NoClassDefFoundError e) {
206 if (exceptionOnMissingAnnotationClass)
207
208
209 throw new TypeNotPresentException(sig, e);
210 skipAnnotation(buf, false);
211 return null;
212 }
213 catch (TypeNotPresentException e) {
214 if (exceptionOnMissingAnnotationClass)
215 throw e;
216 skipAnnotation(buf, false);
217 return null;
218 }
219 AnnotationType type = null;
220 try {
221 type = AnnotationType.getInstance(annotationClass);
222 } catch (IllegalArgumentException e) {
223 skipAnnotation(buf, false);
224 return null;
225 }
226
227 Map<String, Class<?>> memberTypes = type.memberTypes();
228 Map<String, Object> memberValues =
229 new LinkedHashMap<String, Object>(type.memberDefaults());
230
231 int numMembers = buf.getShort() & 0xFFFF;
232 for (int i = 0; i < numMembers; i++) {
233 int memberNameIndex = buf.getShort() & 0xFFFF;
234 String memberName = constPool.getUTF8At(memberNameIndex);
235 Class<?> memberType = memberTypes.get(memberName);
236
237 if (memberType == null) {
238
239 skipMemberValue(buf);
240 } else {
241 Object value = parseMemberValue(memberType, buf, constPool, container);
242 if (value instanceof AnnotationTypeMismatchExceptionProxy)
243 ((AnnotationTypeMismatchExceptionProxy) value).
244 setMember(type.members().get(memberName));
245 memberValues.put(memberName, value);
246 }
247 }
248 return annotationForMap(annotationClass, memberValues);
249 }
250
251
252
253
254
255 public static Annotation annotationForMap(
256 Class<? extends Annotation> type, Map<String, Object> memberValues)
257 {
258 return (Annotation) Proxy.newProxyInstance(
259 type.getClassLoader(), new Class[] { type },
260 new AnnotationInvocationHandler(type, memberValues));
261 }
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290 public static Object parseMemberValue(Class<?> memberType,
291 ByteBuffer buf,
292 ConstantPool constPool,
293 Class<?> container) {
294 Object result = null;
295 int tag = buf.get();
296 switch(tag) {
297 case 'e':
298 return parseEnumValue((Class<? extends Enum<?>>)memberType, buf, constPool, container);
299 case 'c':
300 result = parseClassValue(buf, constPool, container);
301 break;
302 case '@':
303 result = parseAnnotation(buf, constPool, container, true);
304 break;
305 case '[':
306 return parseArray(memberType, buf, constPool, container);
307 default:
308 result = parseConst(tag, buf, constPool);
309 }
310
311 if (!(result instanceof ExceptionProxy) &&
312 !memberType.isInstance(result))
313 result = new AnnotationTypeMismatchExceptionProxy(
314 result.getClass() + "[" + result + "]");
315 return result;
316 }
317
318
319
320
321
322
323
324
325
326
327
328 private static Object parseConst(int tag,
329 ByteBuffer buf, ConstantPool constPool) {
330 int constIndex = buf.getShort() & 0xFFFF;
331 switch(tag) {
332 case 'B':
333 return Byte.valueOf((byte) constPool.getIntAt(constIndex));
334 case 'C':
335 return Character.valueOf((char) constPool.getIntAt(constIndex));
336 case 'D':
337 return Double.valueOf(constPool.getDoubleAt(constIndex));
338 case 'F':
339 return Float.valueOf(constPool.getFloatAt(constIndex));
340 case 'I':
341 return Integer.valueOf(constPool.getIntAt(constIndex));
342 case 'J':
343 return Long.valueOf(constPool.getLongAt(constIndex));
344 case 'S':
345 return Short.valueOf((short) constPool.getIntAt(constIndex));
346 case 'Z':
347 return Boolean.valueOf(constPool.getIntAt(constIndex) != 0);
348 case 's':
349 return constPool.getUTF8At(constIndex);
350 default:
351 throw new AnnotationFormatError(
352 "Invalid member-value tag in annotation: " + tag);
353 }
354 }
355
356
357
358
359
360
361
362
363
364 private static Object parseClassValue(ByteBuffer buf,
365 ConstantPool constPool,
366 Class<?> container) {
367 int classIndex = buf.getShort() & 0xFFFF;
368 try {
369 try {
370 String sig = constPool.getUTF8At(classIndex);
371 return parseSig(sig, container);
372 } catch (IllegalArgumentException ex) {
373
374 return constPool.getClassAt(classIndex);
375 }
376 } catch (NoClassDefFoundError e) {
377 return new TypeNotPresentExceptionProxy("[unknown]", e);
378 }
379 catch (TypeNotPresentException e) {
380 return new TypeNotPresentExceptionProxy(e.typeName(), e.getCause());
381 }
382 }
383
384 private static Class<?> parseSig(String sig, Class<?> container) {
385 if (sig.equals("V")) return void.class;
386 SignatureParser parser = SignatureParser.make();
387 TypeSignature typeSig = parser.parseTypeSig(sig);
388 GenericsFactory factory = CoreReflectionFactory.make(container, ClassScope.make(container));
389 Reifier reify = Reifier.make(factory);
390 typeSig.accept(reify);
391 Type result = reify.getResult();
392 return toClass(result);
393 }
394 static Class<?> toClass(Type o) {
395 if (o instanceof GenericArrayType)
396 return Array.newInstance(toClass(((GenericArrayType)o).getGenericComponentType()),
397 0)
398 .getClass();
399 return (Class)o;
400 }
401
402
403
404
405
406
407
408
409
410
411
412
413
414 private static Object parseEnumValue(Class<? extends Enum> enumType, ByteBuffer buf,
415 ConstantPool constPool,
416 Class<?> container) {
417 int typeNameIndex = buf.getShort() & 0xFFFF;
418 String typeName = constPool.getUTF8At(typeNameIndex);
419 int constNameIndex = buf.getShort() & 0xFFFF;
420 String constName = constPool.getUTF8At(constNameIndex);
421
422 if (!typeName.endsWith(";")) {
423
424 if (!enumType.getName().equals(typeName))
425 return new AnnotationTypeMismatchExceptionProxy(
426 typeName + "." + constName);
427 } else if (enumType != parseSig(typeName, container)) {
428 return new AnnotationTypeMismatchExceptionProxy(
429 typeName + "." + constName);
430 }
431
432 try {
433 return Enum.valueOf(enumType, constName);
434 } catch(IllegalArgumentException e) {
435 return new EnumConstantNotPresentExceptionProxy(
436 (Class<? extends Enum>)enumType, constName);
437 }
438 }
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454 private static Object parseArray(Class<?> arrayType,
455 ByteBuffer buf,
456 ConstantPool constPool,
457 Class<?> container) {
458 int length = buf.getShort() & 0xFFFF;
459 Class<?> componentType = arrayType.getComponentType();
460
461 if (componentType == byte.class) {
462 return parseByteArray(length, buf, constPool);
463 } else if (componentType == char.class) {
464 return parseCharArray(length, buf, constPool);
465 } else if (componentType == double.class) {
466 return parseDoubleArray(length, buf, constPool);
467 } else if (componentType == float.class) {
468 return parseFloatArray(length, buf, constPool);
469 } else if (componentType == int.class) {
470 return parseIntArray(length, buf, constPool);
471 } else if (componentType == long.class) {
472 return parseLongArray(length, buf, constPool);
473 } else if (componentType == short.class) {
474 return parseShortArray(length, buf, constPool);
475 } else if (componentType == boolean.class) {
476 return parseBooleanArray(length, buf, constPool);
477 } else if (componentType == String.class) {
478 return parseStringArray(length, buf, constPool);
479 } else if (componentType == Class.class) {
480 return parseClassArray(length, buf, constPool, container);
481 } else if (componentType.isEnum()) {
482 return parseEnumArray(length, (Class<? extends Enum>)componentType, buf,
483 constPool, container);
484 } else {
485 assert componentType.isAnnotation();
486 return parseAnnotationArray(length, (Class <? extends Annotation>)componentType, buf,
487 constPool, container);
488 }
489 }
490
491 private static Object parseByteArray(int length,
492 ByteBuffer buf, ConstantPool constPool) {
493 byte[] result = new byte[length];
494 boolean typeMismatch = false;
495 int tag = 0;
496
497 for (int i = 0; i < length; i++) {
498 tag = buf.get();
499 if (tag == 'B') {
500 int index = buf.getShort() & 0xFFFF;
501 result[i] = (byte) constPool.getIntAt(index);
502 } else {
503 skipMemberValue(tag, buf);
504 typeMismatch = true;
505 }
506 }
507 return typeMismatch ? exceptionProxy(tag) : result;
508 }
509
510 private static Object parseCharArray(int length,
511 ByteBuffer buf, ConstantPool constPool) {
512 char[] result = new char[length];
513 boolean typeMismatch = false;
514 byte tag = 0;
515
516 for (int i = 0; i < length; i++) {
517 tag = buf.get();
518 if (tag == 'C') {
519 int index = buf.getShort() & 0xFFFF;
520 result[i] = (char) constPool.getIntAt(index);
521 } else {
522 skipMemberValue(tag, buf);
523 typeMismatch = true;
524 }
525 }
526 return typeMismatch ? exceptionProxy(tag) : result;
527 }
528
529 private static Object parseDoubleArray(int length,
530 ByteBuffer buf, ConstantPool constPool) {
531 double[] result = new double[length];
532 boolean typeMismatch = false;
533 int tag = 0;
534
535 for (int i = 0; i < length; i++) {
536 tag = buf.get();
537 if (tag == 'D') {
538 int index = buf.getShort() & 0xFFFF;
539 result[i] = constPool.getDoubleAt(index);
540 } else {
541 skipMemberValue(tag, buf);
542 typeMismatch = true;
543 }
544 }
545 return typeMismatch ? exceptionProxy(tag) : result;
546 }
547
548 private static Object parseFloatArray(int length,
549 ByteBuffer buf, ConstantPool constPool) {
550 float[] result = new float[length];
551 boolean typeMismatch = false;
552 int tag = 0;
553
554 for (int i = 0; i < length; i++) {
555 tag = buf.get();
556 if (tag == 'F') {
557 int index = buf.getShort() & 0xFFFF;
558 result[i] = constPool.getFloatAt(index);
559 } else {
560 skipMemberValue(tag, buf);
561 typeMismatch = true;
562 }
563 }
564 return typeMismatch ? exceptionProxy(tag) : result;
565 }
566
567 private static Object parseIntArray(int length,
568 ByteBuffer buf, ConstantPool constPool) {
569 int[] result = new int[length];
570 boolean typeMismatch = false;
571 int tag = 0;
572
573 for (int i = 0; i < length; i++) {
574 tag = buf.get();
575 if (tag == 'I') {
576 int index = buf.getShort() & 0xFFFF;
577 result[i] = constPool.getIntAt(index);
578 } else {
579 skipMemberValue(tag, buf);
580 typeMismatch = true;
581 }
582 }
583 return typeMismatch ? exceptionProxy(tag) : result;
584 }
585
586 private static Object parseLongArray(int length,
587 ByteBuffer buf, ConstantPool constPool) {
588 long[] result = new long[length];
589 boolean typeMismatch = false;
590 int tag = 0;
591
592 for (int i = 0; i < length; i++) {
593 tag = buf.get();
594 if (tag == 'J') {
595 int index = buf.getShort() & 0xFFFF;
596 result[i] = constPool.getLongAt(index);
597 } else {
598 skipMemberValue(tag, buf);
599 typeMismatch = true;
600 }
601 }
602 return typeMismatch ? exceptionProxy(tag) : result;
603 }
604
605 private static Object parseShortArray(int length,
606 ByteBuffer buf, ConstantPool constPool) {
607 short[] result = new short[length];
608 boolean typeMismatch = false;
609 int tag = 0;
610
611 for (int i = 0; i < length; i++) {
612 tag = buf.get();
613 if (tag == 'S') {
614 int index = buf.getShort() & 0xFFFF;
615 result[i] = (short) constPool.getIntAt(index);
616 } else {
617 skipMemberValue(tag, buf);
618 typeMismatch = true;
619 }
620 }
621 return typeMismatch ? exceptionProxy(tag) : result;
622 }
623
624 private static Object parseBooleanArray(int length,
625 ByteBuffer buf, ConstantPool constPool) {
626 boolean[] result = new boolean[length];
627 boolean typeMismatch = false;
628 int tag = 0;
629
630 for (int i = 0; i < length; i++) {
631 tag = buf.get();
632 if (tag == 'Z') {
633 int index = buf.getShort() & 0xFFFF;
634 result[i] = (constPool.getIntAt(index) != 0);
635 } else {
636 skipMemberValue(tag, buf);
637 typeMismatch = true;
638 }
639 }
640 return typeMismatch ? exceptionProxy(tag) : result;
641 }
642
643 private static Object parseStringArray(int length,
644 ByteBuffer buf, ConstantPool constPool) {
645 String[] result = new String[length];
646 boolean typeMismatch = false;
647 int tag = 0;
648
649 for (int i = 0; i < length; i++) {
650 tag = buf.get();
651 if (tag == 's') {
652 int index = buf.getShort() & 0xFFFF;
653 result[i] = constPool.getUTF8At(index);
654 } else {
655 skipMemberValue(tag, buf);
656 typeMismatch = true;
657 }
658 }
659 return typeMismatch ? exceptionProxy(tag) : result;
660 }
661
662 private static Object parseClassArray(int length,
663 ByteBuffer buf,
664 ConstantPool constPool,
665 Class<?> container) {
666 Object[] result = new Class<?>[length];
667 boolean typeMismatch = false;
668 int tag = 0;
669
670 for (int i = 0; i < length; i++) {
671 tag = buf.get();
672 if (tag == 'c') {
673 result[i] = parseClassValue(buf, constPool, container);
674 } else {
675 skipMemberValue(tag, buf);
676 typeMismatch = true;
677 }
678 }
679 return typeMismatch ? exceptionProxy(tag) : result;
680 }
681
682 private static Object parseEnumArray(int length, Class<? extends Enum> enumType,
683 ByteBuffer buf,
684 ConstantPool constPool,
685 Class<?> container) {
686 Object[] result = (Object[]) Array.newInstance(enumType, length);
687 boolean typeMismatch = false;
688 int tag = 0;
689
690 for (int i = 0; i < length; i++) {
691 tag = buf.get();
692 if (tag == 'e') {
693 result[i] = parseEnumValue(enumType, buf, constPool, container);
694 } else {
695 skipMemberValue(tag, buf);
696 typeMismatch = true;
697 }
698 }
699 return typeMismatch ? exceptionProxy(tag) : result;
700 }
701
702 private static Object parseAnnotationArray(int length,
703 Class<? extends Annotation> annotationType,
704 ByteBuffer buf,
705 ConstantPool constPool,
706 Class<?> container) {
707 Object[] result = (Object[]) Array.newInstance(annotationType, length);
708 boolean typeMismatch = false;
709 int tag = 0;
710
711 for (int i = 0; i < length; i++) {
712 tag = buf.get();
713 if (tag == '@') {
714 result[i] = parseAnnotation(buf, constPool, container, true);
715 } else {
716 skipMemberValue(tag, buf);
717 typeMismatch = true;
718 }
719 }
720 return typeMismatch ? exceptionProxy(tag) : result;
721 }
722
723
724
725
726
727 private static ExceptionProxy exceptionProxy(int tag) {
728 return new AnnotationTypeMismatchExceptionProxy(
729 "Array with component tag: " + tag);
730 }
731
732
733
734
735
736
737
738
739
740
741 private static void skipAnnotation(ByteBuffer buf, boolean complete) {
742 if (complete)
743 buf.getShort();
744 int numMembers = buf.getShort() & 0xFFFF;
745 for (int i = 0; i < numMembers; i++) {
746 buf.getShort();
747 skipMemberValue(buf);
748 }
749 }
750
751
752
753
754
755
756 private static void skipMemberValue(ByteBuffer buf) {
757 int tag = buf.get();
758 skipMemberValue(tag, buf);
759 }
760
761
762
763
764
765
766 private static void skipMemberValue(int tag, ByteBuffer buf) {
767 switch(tag) {
768 case 'e':
769 buf.getInt();
770 break;
771 case '@':
772 skipAnnotation(buf, true);
773 break;
774 case '[':
775 skipArray(buf);
776 break;
777 default:
778
779 buf.getShort();
780 }
781 }
782
783
784
785
786
787
788 private static void skipArray(ByteBuffer buf) {
789 int length = buf.getShort() & 0xFFFF;
790 for (int i = 0; i < length; i++)
791 skipMemberValue(buf);
792 }
793
794
795
796
797
798
799
800
801 private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
802 public static Annotation[] toArray(Map<Class<? extends Annotation>, Annotation> annotations) {
803 return annotations.values().toArray(EMPTY_ANNOTATION_ARRAY);
804 }
805 }